# 12. Cookie、Session、Token区别

# http是无状态的协议

HTTP是一种不保存状态的,无状态的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,自身不具备保存之前发送过的请求或响应信息的功能。每当有新的请求发送时,就会有对应的新响应产生。这是为了快速的处理大量事务,确保协议的可伸缩性。

至于为什么HTTP没状态,可能是因为HTTP协议设计时一是为了简单考虑二是早期没考虑到现在web发展需求这个情况。

HTTP/1.1虽然是无状态协议,但为了实现保持状态功能,于是引入了Cookie技术。

如果只用Cookie来识别用户状态,那么用户信息会全部保存在客户端,虽然也可以实现服务器识别用户状态,但会造成以下问题:

  1. 可能造成CSRF安全问题,一旦数据泄露,那么攻击者就可以伪造用户做一些危险操作。
  2. Cookie只有4k容量,数据量大时可能会造成空间不足,而且网络传输的数据量也会变大。

# Session

因为Cookie非常容易造成安全问题,所以就有了Session+Cookie。过程如下:

  1. 客户端登录时发送请求
  2. 服务端接收到请求验证登录通过后,建立一个sessionid随机字符串。并在响应头字段Set-Cookie中返回sessionId。Set-Cookie格式如下
Set-Cookie: sessionId:xxx
1
  1. 客户端再次发送请求时浏览器会自动在Cookie中包含sessionid发送到服务端。
  2. 服务端接收到请求后对比sessionid,然后获取到用户信息。

Session只需要在客户端保存一个id,实际上大量数据都是保存在服务端。禁用Cookie后还有其他方法存储,比如放在url中。会出现以下问题:

  1. 造成CSRF安全问题
  2. 用户信息全部放在服务端会造成服务器压力

# Token

因为Session+Cookie的方式会造成安全问题和可能会造成服务器压力过大的问题,就有了token。token 也称作令牌。服务端并不会保存身份认证相关的数据。

# 组成

uid: 用户唯一身份标识
time: 当前时间的时间戳
sign: 签名, 使用 hash/encrypt 压缩成定长的十六进制字符串,以防止第三方恶意拼接
固定参数(可选): 将一些常用的固定参数加入到 token 中是为了避免重复查库

# 存放

token在客户端一般存放于localStorage,cookie,或sessionStorage中。在服务器一般存于数据库中。

# 认证流程

token 的认证流程与cookie很相似

  1. 用户登录,成功后服务器返回Token给客户端。
  2. 客户端收到数据后保存在客户端
  3. 客户端再次访问服务器,将token放入headers中
  4. 服务器端采用filter过滤器校验。校验成功则返回请求数据,校验失败则返回错误码

token是开发者为了防范csrf而特别设计的令牌,浏览器不会自动添加到headers里,攻击者也无法访问用户的token,所以提交的表单无法通过服务器过滤,也就无法形成攻击。

# 参考

https://segmentfault.com/a/1190000017831088 (opens new window)


# 补充:Cookie、Session、Token 全面对比

在 Web 开发中,Cookie、Session、Token 是用于用户身份认证和会话管理的三种核心机制。你可以把它们想象成三种不同的“通行证”设计。

# 一、一句话理解

机制 一句话概括 存放位置
Cookie 浏览器里的“便签纸”,用来存少量数据(如用户 ID),每次请求自动带上 浏览器端
Session 服务器端的“档案柜”,存用户状态(如登录信息),通过 Session ID 查找 服务器端
Token 一个“加密签名令牌”,包含用户信息和有效期,服务端通过签名验证真实性 客户端(通常存在 localStorage 或 Cookie)

# 二、核心原理对比

Cookie 是浏览器自带的一种存储机制,由服务器通过 HTTP 响应头的 Set-Cookie 字段设置,浏览器会将其保存并在后续请求中自动携带。

┌─────────────┐         Set-Cookie: user_id=123         ┌─────────────┐
│   浏览器    │ ◄────────────────────────────────────── │   服务器    │
│  (存Cookie) │ ──────────────────────────────────────► │  (设置Cookie)│
└─────────────┘      每次请求自动携带 Cookie           └─────────────┘
1
2
3
4

特点:

  • 自动携带:浏览器在请求同一域名时会自动带上 Cookie,不需要手动处理
  • 大小限制:每个域名下最多 4KB
  • 安全性:可设置 HttpOnly(禁止 JS 读取)和 Secure(仅 HTTPS 传输)

# 2. Session

Session 是服务端存储的用户状态数据。当用户登录后,服务端会创建一个 Session,生成一个唯一的 Session ID,并通过 Cookie 返回给客户端。

┌─────────────┐    Cookie: session_id=abc123    ┌─────────────┐
│   浏览器    │ ────────────────────────────────► │   服务器    │
│  (存Session │ ◄──────────────────────────────── │  (存用户数据)│
│    ID)      │      返回 Session 对应的数据     │  Session:   │
└─────────────┘                                 │   {user:张三}│
                                                └─────────────┘
1
2
3
4
5
6

特点:

  • 服务端存储:数据存在服务器内存或 Redis 中,客户端只存一个 ID
  • 状态保持:Session 有有效期,过期后自动销毁
  • 安全性较高:数据在服务端,客户端无法篡改
  • 缺点:分布式部署时需要共享 Session(如用 Redis 集中存储)

# 3. Token

Token 是一种自包含的加密令牌,服务端通过签名验证 Token 的合法性和有效性。最常用的是 JWT(JSON Web Token)。

┌─────────────┐     Authorization: Bearer xxx     ┌─────────────┐
│   浏览器    │ ───────────────────────────────────► │   服务器    │
│  (存Token)  │                                     │  (验证签名) │
└─────────────┘ ◄────────────────────────────────── └─────────────┘
               返回数据                              Token 合法则放行
1
2
3
4
5

JWT 结构:

Header.Payload.Signature
eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOiIxMjMifQ.xxxxxx
  ↓                    ↓                    ↓
 算法                 用户信息              签名
1
2
3
4

特点:

  • 无状态:服务端不需要存储 Token,验证签名即可
  • 自包含:Token 里包含了用户信息(如 user_id),服务端可以直接解码使用
  • 跨域友好:适合移动端和多域名场景
  • 缺点:Token 一旦签发,在过期前无法主动撤销(需要额外维护黑名单)

# 三、区别对比表

维度 Cookie Session Token (JWT)
存储位置 浏览器端 服务器端(内存/Redis) 客户端(localStorage/Cookie)
数据大小 ≤ 4KB 不限(取决于服务器内存) 较大(包含用户信息)
是否状态 无状态(仅存数据) 有状态(服务端存数据) 无状态(自包含)
安全性 低(容易被窃取) 较高(数据在服务端) 高(依赖签名算法)
跨域支持 需配置 withCredentials 需共享 Session 存储 ✅ 天然支持
移动端支持 ❌ 不支持(App 无浏览器 Cookie) ❌ 不支持 ✅ 支持
注销/登出 清除 Cookie 删除服务端 Session 记录 清理客户端 Token(但 Token 在服务端仍有效)
分布式扩展 简单 需要 Session 共享(如 Redis) ✅ 天然支持
典型场景 存储小数据、跟踪会话 Web 应用登录状态 RESTful API、移动应用、微服务

# 四、三种方案的安全建议

机制 常见攻击 防范措施
Cookie XSS(窃取 Cookie) 设置 HttpOnly、Secure、SameSite
Session CSRF(跨站请求伪造) 使用 CSRF Token、SameSite 属性
Token XSS(窃取 Token) 存 httpOnly Cookie 或内存中,避免存 localStorage

# 五、面试回答话术

Cookie、Session、Token 是 Web 开发中用于身份认证和会话管理的三种机制:

Cookie 是浏览器提供的存储机制,数据保存在客户端,每次请求会自动携带。适合存储少量数据,但需要注意安全设置,比如 HttpOnly 防止 XSS 攻击。

Session 是服务端存储的用户状态,客户端只存一个 Session ID。它的数据更安全,但在分布式环境下需要共享 Session 存储(如 Redis)。适合传统的 Web 应用。

Token(最常见的是 JWT)是一种自包含的加密令牌,包含了用户信息和签名,服务端通过验证签名来确认身份。它是无状态的,天然支持跨域和分布式场景,适合 RESTful API、移动应用和微服务架构。

三者的演进关系:

  • Cookie 是最基础的存储机制
  • Session 是基于 Cookie 的服务端状态管理
  • Token 是更现代的、无状态的认证方案,解决了 Session 在分布式和跨域场景下的局限性

在实际项目中,我会根据业务场景选择:

  • 传统的服务端渲染 Web 应用 → Session
  • 前后端分离的 RESTful API → Token (JWT)
  • 同时设置 httpOnly Cookie 存储 Token,兼顾安全和便利

# 六、Token 与 Session 的核心取舍

Session 模式:服务器存数据,压力在服务端
Token 模式:客户端存数据,压力在带宽和签名验证
1
2
  • 选择 Session:如果你需要服务端主动撤销登录,且用户量可控
  • 选择 Token:如果你需要跨域、移动端支持,或分布式扩展

# 七、一句话总结

Cookie 是“浏览器贴纸”,Session 是“服务器档案柜”,Token 是“带签名的电子门禁卡”。

三者常组合使用:用 Cookie 存 Session ID 或 Token,用 Session 存敏感状态,用 Token 做无状态认证。理解它们的区别和适用场景,是设计安全、可扩展的认证系统的基础。